package com.gitee.xmhzzz.component.spring.cloud.component.dao.annotation;

import com.gitee.xmhzzz.component.common.dto.PageBase;
import com.gitee.xmhzzz.component.spring.cloud.component.dao.config.DaoConfig;
import com.gitee.xmhzzz.component.spring.cloud.component.dao.context.PageContextMng;
import com.gitee.xmhzzz.component.spring.cloud.component.dao.context.PageLimiter;
import com.gitee.xmhzzz.component.spring.cloud.component.dao.utils.PageUtil;
import com.github.pagehelper.PageHelper;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.Arrays;

/**
  * @ClassName
  * @Description
  * @Author wzq
  * @Date 2023/12/15 16:38
  * @Version 1.0
  */
@Component
@Aspect
@Slf4j
@EnableConfigurationProperties({DaoConfig.class})
public class PageAdvice {

    @Autowired
    private DaoConfig daoConfig;

    @Pointcut("@annotation(com.gitee.xmhzzz.component.spring.cloud.component.dao.annotation.Pageable)")
    void pointcut() {
    }


    @Around("pointcut()")
    public Object pagePointcut(ProceedingJoinPoint joinPoint) throws Exception {
        //分页操作
        pageOperation(joinPoint);
        try {
            return joinPoint.proceed();
        } catch (Throwable e) {
            if (e instanceof Exception) {
                throw (Exception) e;
            }
            throw new RuntimeException(e);
        } finally {
            PageHelper.clearPage();
            PageContextMng.clear();
        }
    }

    private void pageOperation(ProceedingJoinPoint joinPoint) {
        if (!daoConfig.isPageHelperEnable()) {
            return;
        }
        String methodName = null;
        PageBase pageParam = null;
        try {
            Object[] args = joinPoint.getArgs();
            Signature signature = joinPoint.getSignature();
            MethodSignature methodSignature = (MethodSignature) signature;
            Method method = methodSignature.getMethod();
            methodName = method.getName();
            //获取分页参数
            Pageable pageable = method.getAnnotation(Pageable.class);
            if (pageable != null) {
                //获取到方法的所有参数名称的字符串数组
                pageParam = getPageParam(args);
                Integer page = pageParam.getCurrent();
                Integer size = pageParam.getSize();
                page = page != null ? page : pageable.defaultPage();
                size = size != null ? size : pageable.defaultSize();
                PageBase pageBase = new PageBase();
                pageBase.setCurrent(page);
                pageBase.setSize(size);
                PageUtil.setPage(new PageLimiter(pageable.maxPage(), pageable.maxSize()).resetPage(pageBase));
                if (pageable.auto()) {
                    PageUtil.startPage(pageable.count());
                }
            }
        } catch (Exception e) {
            log.warn("方法：{} 设置分页参数失败:参数：{}，e：{}", methodName, pageParam, e);
        }

    }

    private PageBase getPageParam(Object[] args) {
        PageBase pageBase = (PageBase) Arrays.stream(args).filter(o -> o instanceof PageBase).findFirst().orElse(null);
        return pageBase;
    }
}
